package com.wendal.java.vfilesystem;

import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class VFileIndex implements Serializable , Cloneable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -8836624873687809671L;

	private Map<String, VFile> map;
	
	private boolean [] index ;
	
	private VFileIndex() {
		
	}
	
	public VFileIndex(int indexSize) {
		if(indexSize < 1) return;
		map = new HashMap<String, VFile>();
		index = new boolean[indexSize];
		Arrays.fill(index, false);
	}
	
	public VFile getVFile(String key){
		return map.get(key);
	}
	
	public void addVFile(String key,VFile file){
		map.put(key, file);
	}
	
	public void remove(String key){
		VFile file = map.remove(key);
		if(file != null){
			int [] blocks = file.getBlocks();
			for (int i = 0; i < blocks.length; i++) {
				index[blocks[i]] = false;
			}
		}
	}
	
	public void reset(){
		map.clear();
		Arrays.fill(index, false);
	}
	
	public int [] getAvailableBlock(final int size) throws IOException{
		int [] blocks = new int[size];
		int pointer = 0;
		for (int i = 0; i < index.length; i++) {
			if(index[i] == false){
				blocks[pointer] = i;
				pointer++;
				if(pointer == size){
					break;
				}
			}
		}
		if(pointer != size) throw new IOException("Disk is full!");
		return blocks;
	}
	
	public void maskFlag(int [] blocks,boolean flag){
		for (int i = 0; i < blocks.length; i++) {
			index[blocks[i]] = flag;
		}
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public VFileIndex clone() {
		VFileIndex fileIndex = new VFileIndex();
		try {
			Map<String, VFile> tmpMap = this.map.getClass().newInstance();
			fileIndex.map = tmpMap;
			for (String tmpKey : map.keySet()) {
				tmpMap.put(tmpKey, map.get(tmpKey));
			}
			boolean [] tmpIndex = new boolean[this.index.length];
			fileIndex.index = tmpIndex;
			for (int i = 0; i < tmpIndex.length; i++) {
				tmpIndex[i] = this.index[i];
			}
		} catch (InstantiationException e) {
			//Do nothing
		} catch (IllegalAccessException e) {
			//Do nothing
		}
		return fileIndex;
	}
}
